home *** CD-ROM | disk | FTP | other *** search
/ Magnum One / Magnum One (Mid-American Digital) (Disc Manufacturing).iso / d1 / freemacs.arc / MINTFORM.ASM < prev    next >
Assembly Source File  |  1988-03-17  |  9KB  |  343 lines

  1. ;History:173,1
  2.     page    ,132
  3.  
  4.     .xlist
  5.     include    mintdefs.asm
  6.     .list
  7.  
  8. data    segment byte public
  9.     extrn    formb:    word
  10.     extrn    forme:    word
  11.     extrn    fend: word
  12.     extrn    actptr:    word
  13.  
  14. comment /
  15.     formhash is the hashing table for form names.  It is a list of
  16. pointers to forms.  Each form, in turn, has a pointer to the next form whose
  17. name hashes to the same entry in formhash. To add a new form, we must add the
  18. name to the proper place in the table.  To delete a form, the form name must
  19. be removed from formhash. After the remaining forms have been moved up in
  20. memory, their links in formhash and each of the forms must be updated.
  21.     We use -1 for NIL because is above any legal address that a form may
  22. take on.  When we adjust the hash links, we won't adjust any NILs because they
  23. seem to be a form which is above the one being moved. /
  24.  
  25.     public    syntax_table
  26. syntax_table    dw    NIL
  27. ;don't put anything here.
  28. formhashsize    equ    256
  29.     public    formhash    ;formhash is public for debugging purposes only.
  30. formhash    dw formhashsize dup(NIL)
  31.  
  32. hash_value    dw    ?
  33.  
  34. data    ends
  35.  
  36. code    segment byte public
  37.  
  38.     assume cs:code, ds: data, es: data
  39.  
  40.  
  41. ;define a form.  Enter with:
  42. ;    si => name
  43. ;    cx = name length
  44. ;    di => data
  45. ;    dx = data length
  46. ;    bx = form pointer.
  47.  
  48. ;this is what is accomplished: (a=active string, n=new form, o=old forms)
  49. ;  aaaa     nnnnnnnn   ooooooo     oooooooo
  50. ;  ^                   ^                    ^
  51. ;actptr               formb                forme
  52. ;  ^<------>^
  53. ;  di  cx   si
  54.  
  55.  
  56.     public    define_form
  57. define_form:
  58.     push    bx            ;save the form pointer.
  59.     call    find_form        ;see if it already exists.
  60.     jnc    define_form_1        ;it doesn't.
  61. ;check to see if the form is already big enough.
  62.     cmp    dx,[bx].data_length
  63.     ja    define_form_3        ;it isn't.
  64.     pop    [bx].form_pointer    ;set the form pointer.
  65.     mov    si,di            ;prepare to move the data.
  66.     lea    di,[bx].name_offset    ;->name.
  67.     add    di,cx            ;->data.
  68.     mov    [bx].data_length,dx    ;set the data length.
  69.     jmp    short define_form_4
  70. define_form_3:
  71.     push    di
  72.     push    si
  73.     push    cx
  74.     call    delete_form
  75.     pop    cx
  76.     pop    si
  77.     pop    di
  78. define_form_1:
  79.     pop    bx        ;restore form pointer.
  80.     push    di
  81.     push    si
  82.     push    cx
  83.     add    cx,(size form)    ;compute amount of space needed.
  84.     add    cx,dx
  85.     push    cx        ;push the size
  86.     mov    si,actptr
  87.     mov    di,si
  88.     sub    di,cx
  89.     mov    ax,di        ;see if we have that much space.
  90.     sub    ax,free_space
  91.     cmp    ax,fend
  92.     jb    define_form_2    ;no, go show no mem
  93.     mov    cx,formb    ;compute the number of bytes to move.
  94.     sub    cx,actptr
  95.     mov    actptr,di    ;update actptr
  96.     rep    movsb
  97. ;di points to the free space.  Leave it alone.
  98.     mov    formb,di
  99.     pop    [di].form_length    ;get the total size. (pushed as cx)
  100.     mov    [di].form_pointer,bx
  101.     pop    cx            ;we have to pop into cx, because we
  102.     mov    [di].name_length,cx    ;  need it later for the movsb.
  103.     mov    [di].data_length,dx
  104.     pop    si            ;restore ->name
  105.     call    hash_func
  106.     mov    ax,[bx]            ;get current formhash
  107.     mov    [bx],di            ;make formhash point to us.
  108.     mov    [di].hash_link,ax    ;make us point to current formhash.
  109.     add    di,name_offset        ;lea    di,[di].name_offset
  110.     rep    movsb
  111.     pop    si            ;restore ->data
  112. define_form_4:
  113. ;here with dx=data size, si->data, di->data area in form.
  114.     mov    cx,dx
  115.     rep    movsb
  116.     ret
  117. define_form_2:
  118.     jmp    nomem
  119.  
  120.  
  121. ;Find a form.  Enter with:
  122. ;    si => name
  123. ;    cx = name length
  124. ;Preserve di
  125. ;Exit with:
  126. ;    bx => form
  127. ;    cy if form found,
  128. ;    nc if form not found.
  129.     public    find_form
  130. find_form:
  131.     push    dx
  132.     push    di
  133.     call    hash_func
  134.     mov    hash_value,bx        ;remember the formhash pointer.
  135.     xor    dx,dx
  136.     mov    bx,[bx]            ;get ->first form that hashes here.
  137. find_form_1:
  138.     cmp    bx,NIL            ;end of list?
  139.     je    find_form_2        ;yes, we didn't find it.
  140.     cmp    cx,[bx].name_length    ;lengths equal?
  141.     jne    find_form_3        ;no, go to next.
  142.     lea    di,[bx].name_offset    ;compare names.
  143.     push    si
  144.     push    cx
  145.     rep    cmpsb
  146.     pop    cx
  147.     pop    si
  148.     jne    find_form_3        ;names not equal.
  149.     or    dx,dx            ;did we find it first?
  150.     je    find_form_4        ;yes - that's where we want it.
  151.     mov    di,hash_value        ;get the head of the list.
  152.     mov    ax,[di]
  153.     mov    [di],bx            ;make head -> found.
  154.     xchg    ax,[bx].hash_link    ;make found -> old head.
  155.     mov    di,dx
  156.     mov    [di].hash_link,ax    ;make pred(found) -> succ(found).
  157. find_form_4:
  158.     stc                ;found the form!
  159.     pop    di
  160.     pop    dx
  161.     ret
  162. find_form_3:
  163.     mov    dx,bx
  164.     mov    bx,[bx].hash_link
  165.     jmp    find_form_1
  166. find_form_2:
  167.     clc            ;didn't find the form!
  168.     pop    di
  169.     pop    dx
  170.     ret
  171.  
  172.  
  173. ;delete a form.  Enter with:
  174. ;    bx=>form
  175. ;this is what is accomplished: (a=active string, f=forms, d=deleted form)
  176. ;  aaaa     ffffffff      ddddddddddd    ffffffff
  177. ;  ^        ^             ^   ^^^^^^^            ^
  178. ;actptr   formb          bx   delete           forme
  179. ;  <-------------->^                ^
  180. ;         cx       si               di
  181.  
  182.  
  183.     public    delete_form
  184. delete_form:
  185. ;delete the form from the hashing table.
  186.     mov    di,bx            ;make a copy of the pointer to the form.
  187.     mov    cx,[bx].name_length
  188.     lea    si,[bx].name_offset
  189.     call    hash_func
  190.     sub    bx,hash_link        ;pretend that formhash is a form itself.
  191. delete_form_1:
  192.     cmp    [bx].hash_link,di    ;does this form point to us?
  193.     je    delete_form_2        ;yes.
  194.     mov    bx,[bx].hash_link    ;no - go to the next form.
  195.     jmp    delete_form_1
  196. delete_form_2:
  197.     mov    ax,[di].hash_link    ;unlink us from the list.
  198.     mov    [bx].hash_link,ax
  199. ;check for deletion of the syntax table.
  200.     cmp    di,syntax_table
  201.     jne    delete_form_7
  202.     mov    syntax_table,NIL    ;if we're deleting it, put NIL in.
  203. delete_form_7:
  204. ;now adjust the hash links in formhash.
  205.     mov    ax,[di].form_length
  206.     mov    bx,offset syntax_table
  207.     mov    cx,formhashsize+1    ;add one for the syntax table.
  208. delete_form_3:
  209.     cmp    [bx],di            ;do we need to adjust this one?
  210.     jae    delete_form_4        ;no.
  211.     add    [bx],ax            ;yes - do it.
  212. delete_form_4:
  213.     add    bx,2
  214.     loop    delete_form_3
  215. ;now adjust all the hash links in the forms.  Notice that we are adjusting
  216. ;  the hash link in the form we are about to delete, but it doesn't hurt.
  217. ;  We can also presume the existence of at least one form at this point.
  218.     mov    bx,formb
  219. delete_form_5:
  220.     cmp    [bx].hash_link,di    ;do we need to adjust this one?
  221.     jae    delete_form_6        ;no.
  222.     add    [bx].hash_link,ax    ;yes - do it.
  223. delete_form_6:
  224.     add    bx,[bx].form_length    ;compute the form after this one.
  225.     cmp    bx,forme        ;no forms after this one.
  226.     jb    delete_form_5
  227.     add    formb,ax
  228.     mov    si,di            ;now move everything up.
  229.     add    di,ax
  230.     mov    cx,si
  231.     sub    cx,actptr
  232.     dec    si
  233.     dec    di
  234.     std                ;reverse move
  235.     rep    movsb
  236.     cld
  237.     inc    di            ;update actptr
  238.     mov    actptr,di
  239.     ret
  240.  
  241.  
  242. ;find the form whose name is given in arg1.  Return the form pointer in
  243. ;si, and the number of bytes remaining in the form in cx.
  244.     public    find_arg1
  245. find_arg1:
  246.     mov    cx,1
  247. ;fall through to find_arg
  248.  
  249. ;find the form whose name is given in the argument specified in cx.  Return
  250. ;  the form pointer in si, and the number of bytes remaining in the form in cx,
  251. ;  and the pointer to the form in bx.
  252.     public    find_arg
  253. find_arg:
  254.     call    getarg
  255.     call    find_form
  256.     jnc    find_arg1_1        ;if form doesn't exist, exit.
  257.     mov    si,bx            ;make si => form.data
  258.     add    si,name_offset
  259.     add    si,[bx].name_length
  260.     add    si,[bx].form_pointer
  261.     mov    cx,[bx].data_length    ;make cx = number of bytes left.
  262.     sub    cx,[bx].form_pointer
  263.     stc                ;remember that form was found.
  264. find_arg1_1:
  265.     ret
  266.  
  267.  
  268. ;rehash is used when the hash structure is garbage, i.e., when a file has
  269. ;  been bulk-loaded.
  270.  
  271.     public    rehash
  272. rehash:
  273.     mov    di,offset formhash    ;kill all of the current pointers.
  274.     mov    cx,formhashsize
  275.     mov    ax,NIL
  276.     rep    stosw
  277.     mov    di,formb
  278. rehash_1:
  279.     lea    si,[di].name_offset    ;->name.
  280.     mov    cx,[di].name_length
  281.     call    hash_func
  282.     mov    ax,[bx]            ;get current formhash
  283.     mov    [bx],di            ;make formhash point to us.
  284.     mov    [di].hash_link,ax    ;make us point to current formhash.
  285.     add    di,[di].form_length
  286.     cmp    di,forme
  287.     jb    rehash_1
  288.     ret
  289.  
  290.  
  291. hash_func:
  292. ;enter with si,cx ->name to be hashed.
  293. ;the particular function we will use is:
  294. ;  value=(((char*2+char)*2+char)*2+char)*2+char ...
  295. ;of course, most of the chars will be in the range [A-Za-z], so this
  296. ;  may not be the best hashing function.  Time will tell.
  297. ;exit with entry into hash table in bx.
  298. ;preserve dl.
  299.     push    si
  300.     push    cx
  301.     xor    bl,bl            ;start with zero.
  302.     jcxz    hash_func_1
  303. hash_func_2:
  304.     add    bl,bl            ;*2
  305.     adc    bl,0
  306.     lodsb
  307.     sub    al,'a'            ;subtract off the most probable char.
  308.     add    bl,al            ;+char
  309.     adc    bl,0
  310.     loop    hash_func_2
  311. hash_func_1:
  312.     mov    bh,0
  313.     add    bx,bx
  314.     lea    bx,formhash[bx]        ;don't add bx,offset formhash!
  315.     pop    cx
  316.     pop    si
  317.     ret
  318.  
  319.  
  320. ;Adjust the form pointer after building a value which affects the
  321. ;  form pointer.  The new form pointer is derived from the count
  322. ;  of characters left in cx.  The form is pointed to by bx.
  323.     public    set_form_pointer
  324. set_form_pointer:
  325.     mov    ax,[bx].data_length
  326.     sub    ax,cx
  327.     mov    [bx].form_pointer,ax
  328.     ret
  329.  
  330.     public    return_form
  331. return_form:
  332.     call    set_form_pointer
  333.     jmp    return_tos
  334.  
  335.  
  336.     extrn    return_tos: near
  337.     extrn    getarg: near
  338.     extrn    nomem: near
  339. code    ends
  340.  
  341.     end
  342.  
  343.